﻿/*
	Copyright (C) 2019 Zongming Liu <1849059316@qq.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License along
	with this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "EventManager.h"
#include "../base/Debuger.h"


namespace
{
	//64 位的数做id 应该够了 
	static uint64_t s_id = 0;
}

namespace SkyEngine2d
{
	
	EventListenerHandle::EventListenerHandle(const std::string& type)
	{
		m_id = s_id;
		m_eventGuid = type;
		++s_id;
	}
	
	EventListenerHandle::EventListenerHandle()
		:m_id(-1)
		, m_eventGuid("")
	{
		
	}
	
	EventManager::EventManager()
	{
	
	}
	
	EventManager::~EventManager()
	{
	
	}
	
	void EventManager::removeListener(const EventListenerHandle& handle)
	{
		auto &f = m_listeners.find(handle.getEventGuid());
		if (f != m_listeners.end())
		{
			f->second->erase(handle.getEventListenerId());
		}
	}
	
	
	void EventManager::triggerEvent(const std::shared_ptr<Event>& e, TriggerMode mode /*= TriggerMode::direct*/)
	{
		if (mode == TriggerMode::direct)
		{
			const auto & f = m_listeners.find(e->getGuid());
			if (f != m_listeners.end())
			{
				auto e_ptr = e.get();
				for (auto & listener : *(f->second))
				{
					listener.second(e_ptr);
					//如果被某个处理 接受事件 ，那么 这个事件被认为处理完毕
					if (e_ptr->isAccept())
					{
						break;
					}
				}
			}
		}
		else
		{
			m_eventQueue.push_back(e);
		}
	}
	
	
	void EventManager::eventLoop() 
	{
		if (m_eventQueue.size()>0)
		{
			auto iter = m_eventQueue.begin();
			for (; iter != m_eventQueue.end();iter++)
			{
				auto type = (*iter)->getGuid();
				const auto & f = m_listeners.find(type);
				if (f != m_listeners.end())
				{
					auto e_ptr = (*iter).get();
					DebugerAssert(e_ptr,"事件的指针为null");
					for (const auto & listener : *(f->second))
					{
						listener.second(e_ptr);
						if (e_ptr->isAccept())
						{
							break;
						}
					}
				}
			}
			m_eventQueue.clear();
		}
	}
}
